package racer.server;

import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.charset.CharacterCodingException;
import java.nio.channels.SocketChannel;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class Player {

	private static final int BUFSIZE = 1024;
	private static final String CHARSET = "ISO-8859-1";
	
	private SocketChannel sockChann;
	private ByteBuffer buffin, buffout;
	private CharBuffer charbuff;
	private Charset charset;
	private CharsetDecoder decoder;
	private RaceServer rc;
	
	public Player(SocketChannel sockChann, RaceServer rc) {
		this.rc = rc;
		this.sockChann = sockChann;
		buffin = ByteBuffer.allocateDirect(BUFSIZE);
		buffin.clear();
		
		charset = Charset.forName(CHARSET);
		decoder = charset.newDecoder();
	}
	
	public String recvMessage() {
		String msg = null;
		try {
			int numBytesRead = sockChann.read(buffin);
			if (numBytesRead == -1) {
				// close channel, inform RaceServer one or the other way
				rc.removeChannel(sockChann);
				return null;
			}
			msg = getMessage(buffin);
		} catch (IOException io) {
			io.printStackTrace();
		}
		
		return msg;
	}
	
	private String getMessage(ByteBuffer buf) {
		String msg = null;
		int pos = buf.position();
		int limit = buf.limit();
		
		buf.position(0);
		buf.limit(pos);
		try {
			CharBuffer charbuff = decoder.decode(buffin);
			msg = charbuff.toString();
		} catch (CharacterCodingException e) {
			e.printStackTrace();
		}
		buf.limit(limit);
		buf.position(pos);
		buf.clear();
		return msg;
	}
	
	public boolean sendMessage(String msg) {
		String fullmsg = msg + "\r\n";
		boolean msgSent = false;
		
		ByteBuffer buffout = ByteBuffer.allocateDirect(BUFSIZE);
		buffout.clear();
		try {
			buffout.put(fullmsg.getBytes());
		} catch (BufferOverflowException e) {
			e.printStackTrace();
		}
		buffout.flip();
		
		try {
			while(buffout.hasRemaining()) {
				sockChann.write(buffout);
			}
			msgSent = true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return msgSent;
	}
	
	public SocketChannel getSockChann() {
		return this.sockChann;
	}
	
}
